import { Vect3 } from "../../../../common/MathUtils";
import { Comp } from "../../CompDef";
import { GpCfg } from "../../GpCfgDef";
import { GpEcsWorld } from "../../GpEcsWorld";
import { GpEventDef } from "../../GpEventDef";
import { EHeroLogicType, EHeroAttriModifyType, EHeroAttriOperationType, HeroLogic, PlayEffEventData } from "../../GpDef";
import { HeroSystem } from "../HeroSystem";
import { logicMap, onTriggerLogic } from "./Utils";
import { gg } from "../../../../../Game";
import ecs, { EcsComponent, EcsEntity } from "ecs-ts";



/**Buff系统 */
export class BuffSystem extends ecs.EcsSystem<GpEcsWorld> {

    buffContainerGroup = this.world.getGroupByClz(Comp.Battle.BuffContainer)

    constructor(world: GpEcsWorld, defaltGroupComps: (new () => EcsComponent)[] = [Comp.Battle.Buff]) {
        super(world, defaltGroupComps);
    }


    public update(): void {
        for (let index = 0; index < this.defaultGroup.entities.length; index++) {
            const entity = this.defaultGroup.entities[index];
            this.checkBuff(entity)
        }
    }

    /**检查buff */
    checkBuff(buffEntity: EcsEntity) {
        const buff = buffEntity.component(Comp.Battle.Buff)
        const buffCfg = gg.cfgById(GpCfg.Buff, buff.cfgId)
        const targetEntity = this.world.getEntity(buff.targetId)
        if (targetEntity) {
            Vect3.set(buffEntity.component(Comp.Transform).pos, targetEntity.component(Comp.Transform).pos)
        }

        if (buff.intervalMs && buff.lastTriggerTimeMs + buff.intervalMs <= this.world.elapsedTimeMs) {
            if (!buff.lastTriggerTimeMs) {
                buff.lastTriggerTimeMs = buff.startTimeMs + buff.intervalMs
            } else {
                buff.lastTriggerTimeMs = this.world.elapsedTimeMs
            }
            this.doBuffLogic(buff, buffCfg.logics)
        }

        if (buff.durationMs && this.world.elapsedTimeMs > buff.startTimeMs + buff.durationMs) {
            this.removeBuff(buffEntity)
        }

    }

    /**添加buff */
    addBuff(containerEntity: EcsEntity, buffCfg: GpCfg.Buff, durationMs = 0) {
        if (!containerEntity) {
            return
        }
        const buffContainerComp = containerEntity.component(Comp.Battle.BuffContainer)
        let buffEntity = this.world.getEntity(buffContainerComp.buffMap[buffCfg.id])
        durationMs = durationMs || (buffCfg.duration * 1000)
        if (!!buffEntity) {
            const buff = buffEntity.component(Comp.Battle.Buff)

            buff.startTimeMs = this.world.elapsedTimeMs

            if (buffCfg.stackMode == 0) {
                buff.durationMs = durationMs
            } else {
                buff.durationMs = durationMs
                buff.stackCount++
                this.doBuffLogic(buff, buffCfg.startLogics)
            }


        } else {
            buffEntity = this.world.addEntityWithComps([Comp.Battle.Buff, Comp.Transform])
            const buff = buffEntity.component(Comp.Battle.Buff)
            buff.cfgId = buffCfg.id
            buff.intervalMs = buffCfg.interval * 1000
            buff.durationMs = durationMs
            buff.startTimeMs = this.world.elapsedTimeMs
            buff.targetId = containerEntity.id
            buffContainerComp.buffMap[buffCfg.id] = buffEntity.id
            buffContainerComp.buffList.push(buffEntity.id)
            buff.stackCount++
            this.doBuffLogic(buff, buffCfg.startLogics)
        }


    }

    doBuffLogic(buff: Comp.Battle.Buff, logics: { t: string, data: number[] }[]) {
        const entity=this.world.getEntity(buff.targetId)
        for (let i = 0; i < logics.length; i++) {
            const logic = GpCfg.Action.cfgLogicToLogic(logics[i]) ;
            onTriggerLogic(this.world, entity, logic)
        }
    }

    /**移除buff */
    removeBuffByType(entity: EcsEntity, buffId: number) {
        const buffContainerComp = entity.component(Comp.Battle.BuffContainer)
        const buffEntity = this.world.getEntity(buffContainerComp.buffMap[buffId])
        if (buffEntity) {
            this.removeBuff(buffEntity)
        }
    }

    /**移除buff */
    removeBuff(buffEntity: EcsEntity) {
        const buff = buffEntity.component(Comp.Battle.Buff)
        const buffCfg = gg.cfgById(GpCfg.Buff, buff.cfgId)
        const targetEntity = this.world.getEntity(buff.targetId)
        if (targetEntity) {

            for (let index = 0; index < buff.stackCount; index++) {
                this.doBuffLogic(buff, buffCfg.endLogics)

            }

            const buffContainerComp = targetEntity.component(Comp.Battle.BuffContainer)
            const buffId = buff.cfgId
            delete (buffContainerComp.buffMap[buffId])
            const index = buffContainerComp.buffList.indexOf(buffEntity.id)
            buffContainerComp.buffList[index] = buffContainerComp.buffList[buffContainerComp.buffList.length - 1]
            buffContainerComp.buffList.pop()
            this.world.removeEntity(buffEntity.id)
        }

    }

    /**是否有buff */
    hasBuff(entity: EcsEntity, buffId: number) {
        const buffContainerComp = entity.component(Comp.Battle.BuffContainer)
        return !!buffContainerComp?.buffMap[buffId]
    }

    /**清空buff */
    clearBuffContainer(buffContainerComp: Comp.Battle.BuffContainer) {
        for (const key in buffContainerComp.buffMap) {
            const buffEntity = this.world.getEntity(buffContainerComp.buffMap[key])
            if (buffEntity) {
                this.removeBuff(buffEntity)
            }

            delete (buffContainerComp.buffMap[key])
        }

    }

}
